package cem.agony;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;

import com.thoughtworks.xstream.XStream;

import cem.agony.model.Rider;
import cem.agony.ui.controller.MapBuilderController;
import cem.agony.ui.controller.RiderOverviewController;
import cem.agony.ui.controller.RootLayoutController;
import cem.agony.ui.controller.RouteBuilderController;
import cem.agony.util.FileUtil;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Dialogs;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class AgonyTracker extends Application
{
    private BorderPane rootLayout;
    private Stage primaryStage;
    private ObservableList<Rider> riderData = FXCollections.observableArrayList();

    public AgonyTracker()
    {
        int index = 1;

        riderData.add( new Rider( index++, "Pete", "Adams" ) );
        riderData.add( new Rider( index++, "Mike", "Lehman" ) );
        riderData.add( new Rider( index++, "Carol", "Lehman" ) );
        riderData.add( new Rider( index++, "John", "Yates" ) );
        riderData.add( new Rider( index++, "Nate", "Boyd" ) );
        riderData.add( new Rider( index++, "Jonathan", "Palmer" ) );
        riderData.add( new Rider( index++, "Mike", "Boone" ) );
        riderData.add( new Rider( index++, "Amy", "Collins" ) );
        riderData.add( new Rider( index++, "Carme", "Barsotti" ) );
        riderData.add( new Rider( index++, "Kirk", "Moberg" ) );
        riderData.add( new Rider( index++, "Carol", "Douglass" ) );
        riderData.add( new Rider( index++, "Caryn", "Galeckas" ) );
        riderData.add( new Rider( index++, "Chris", "Gee" ) );
    }

    public static void main( String[] args )
    {
        launch( args );
    }

    @Override
    public void start( Stage primaryStage )
    {
        this.primaryStage = primaryStage;
        primaryStage.setTitle( "Agony Tracker" );

        try
        {
            FXMLLoader loader = new FXMLLoader( AgonyTracker.class.getResource( "ui/view/RootLayout.fxml" ) );
            rootLayout = (BorderPane) loader.load();
            Scene scene = new Scene( rootLayout );
            primaryStage.setScene( scene );

            RootLayoutController controller = loader.getController();
            controller.setMainApp( this );

            primaryStage.show();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }

        showRiderOverview();

        File file = getRiderFilePath();
        if ( file != null )
        {
            loadRiderDataFromFile( file );
        }
    }

    private void showRiderOverview()
    {
        try
        {
            FXMLLoader loader = new FXMLLoader( AgonyTracker.class.getResource( "ui/view/RiderOverview.fxml" ) );
            AnchorPane overviewPage = (AnchorPane) loader.load();
            rootLayout.setCenter( overviewPage );

            RiderOverviewController controller = loader.getController();
            controller.setMainApp( this );
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

    public boolean showMapBuilderDialog()
    {
        try
        {
            FXMLLoader mapLoader = new FXMLLoader( AgonyTracker.class.getResource( "ui/view/MapBuilder.fxml" ) );
            AnchorPane mapPage = (AnchorPane) mapLoader.load();
            Stage dialogStage = new Stage();
            dialogStage.setTitle( "Map Builder" );
            dialogStage.initModality( Modality.WINDOW_MODAL );
            dialogStage.initOwner( primaryStage );
            Scene mapScene = new Scene( mapPage );
            dialogStage.setScene( mapScene );

            MapBuilderController mapController = mapLoader.getController();
            mapController.setDialogStage( dialogStage );

            dialogStage.showAndWait();

            if ( mapController.isOkayClicked() )
            {
                FXMLLoader routeLoader = new FXMLLoader( AgonyTracker.class.getResource( "ui/view/RouteBuilder.fxml" ) );
                dialogStage.setTitle( "Route Builder" );
                AnchorPane routePage = (AnchorPane) routeLoader.load();
                Scene routeScene = new Scene( routePage );
                dialogStage.setScene( routeScene );

                RouteBuilderController routeController = routeLoader.getController();
                routeController.setDialogStage( dialogStage );

                dialogStage.showAndWait();

                return routeController.isOkayClicked();
            }

            return false;
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            return false;
        }
    }

    public ObservableList<Rider> getRiderData()
    {
        return riderData;
    }

    public Stage getPrimaryStage()
    {
        return primaryStage;
    }

    public File getRiderFilePath()
    {
        Preferences prefs = Preferences.userNodeForPackage( AgonyTracker.class );
        String filePath = prefs.get( "filePath", null );
        if ( filePath != null )
        {
            return new File( filePath );
        }
        return null;
    }

    public void setRiderFilePath( File file )
    {
        Preferences prefs = Preferences.userNodeForPackage( AgonyTracker.class );
        if ( file != null )
        {
            prefs.put( "filePath", file.getPath() );
            primaryStage.setTitle( "Agony Tracker - " + file.getName() );
        }
        else
        {
            prefs.remove( "filePath" );
            primaryStage.setTitle( "Agony Tracker" );
        }
    }

    @SuppressWarnings( "unchecked" )
    public void loadRiderDataFromFile( File file )
    {
        XStream xstream = new XStream();
        xstream.alias( "rider", Rider.class );

        try
        {
            String xml = FileUtil.readFile( file );
            List<Rider> riderList = (ArrayList<Rider>) xstream.fromXML( xml );

            riderData.clear();
            riderData.addAll( riderList );
        }
        catch ( Exception e )
        {
            Dialogs.showErrorDialog( primaryStage,
                                     "Could not load data from file:\n" + file.getPath(),
                                     "Could not load data",
                                     "Error",
                                     e );
        }
    }

    public void saveRiderDataToFile( File file )
    {
        XStream xstream = new XStream();
        xstream.alias( "rider", Rider.class );

        List<Rider> riderList = new ArrayList<Rider>( riderData );
        String xml = xstream.toXML( riderList );

        try
        {
            FileUtil.saveFile( xml, file );
            setRiderFilePath( file );
        }
        catch ( Exception e )
        {
            Dialogs.showErrorDialog( primaryStage,
                                     "Could not save data to file:\n" + file.getPath(),
                                     "Could not save data",
                                     "Error",
                                     e );
        }
    }
}